package com.portal.framework.util;

import java.util.ArrayList;
import java.util.List;

public class SplitUtils {

	@SuppressWarnings("unchecked")
	public static <T, R> SliptResultObject<T> splitList(List<T> lst,
			String propName, Acceptor<R> acceptor) {
		List<T> acceptList = new ArrayList<T>();
		List<T> rejectList = new ArrayList<T>();
		for (T dto : lst) {
			Object fieldValue = ClassUtil.getFieldValue(dto, propName);
			if (acceptor.accept((R) fieldValue)) {
				acceptList.add(dto);
			} else {
				rejectList.add(dto);
			}
		}
		SliptResultObject<T> result = new SliptResultObject<T>();
		result.setAcceptList(acceptList);
		result.setRejectList(rejectList);

		return result;
	}

	public static <T, R> SliptResultObject<T> splitListEquals(List<T> list,
			String propName, Class<R> cls, R value) {
		EqualsAcceptor<R> ea = new EqualsAcceptor<R>();
		ea.setValue(value);
		return splitList(list, propName, ea);
	}

	public static <T, R> SliptResultObject<T> splitListNotEquals(List<T> list,
			String propName, Class<R> cls, R value) {
		NotEqualsAcceptor<R> ea = new NotEqualsAcceptor<R>();
		ea.setValue(value);
		return splitList(list, propName, ea);
	}

	public static <T, R extends Number> SliptResultObject<T> splitListBetween(
			List<T> list, String propName, Class<R> cls, R startValue,
			R endValue) {
		BetweenAcceptor<R> ea = new BetweenAcceptor<R>();
		ea.setStartValue(startValue);
		ea.setEndValue(endValue);
		return splitList(list, propName, ea);
	}

	public static interface Acceptor<R> {
		public boolean accept(R value);
	}

	private static class EqualsAcceptor<R> implements Acceptor<R> {
		private Object value;

		public boolean accept(R value) {
			return this.value.equals(value);
		}

		public Object getValue() {
			return value;
		}

		public void setValue(Object v) {
			this.value = v;
		}
	}

	private static class NotEqualsAcceptor<R> implements Acceptor<R> {
		private Object value;

		public boolean accept(R value) {
			return !this.value.equals(value);
		}

		public Object getValue() {
			return value;
		}

		public void setValue(Object v) {
			this.value = v;
		}
	}

	private static class BetweenAcceptor<R extends Number> implements
			Acceptor<R> {
		private R startValue;
		private R endValue;

		public boolean accept(R value) {
			return value.doubleValue() > startValue.doubleValue()
					&& value.doubleValue() < endValue.doubleValue();
		}

		public R getStartValue() {
			return startValue;
		}

		public void setStartValue(R startValue) {
			this.startValue = startValue;
		}

		public R getEndValue() {
			return endValue;
		}

		public void setEndValue(R endValue) {
			this.endValue = endValue;
		}
	}

	public static class SliptResultObject<T> {
		private List<T> acceptList;
		private List<T> rejectList;

		public List<T> getAcceptList() {
			return acceptList;
		}

		public void setAcceptList(List<T> acceptList) {
			this.acceptList = acceptList;
		}

		public List<T> getRejectList() {
			return rejectList;
		}

		public void setRejectList(List<T> rejectList) {
			this.rejectList = rejectList;
		}

	}
}
